package com.ayu.shortlink.project.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.ayu.shortlink.project.common.constant.RedisKeyConstant;
import com.ayu.shortlink.project.common.convention.exception.ClientException;
import com.ayu.shortlink.project.dao.entity.ShortLinkDO;
import com.ayu.shortlink.project.dao.mapper.ShortLinkMapper;
import com.ayu.shortlink.project.dto.req.*;
import com.ayu.shortlink.project.dto.resp.ShortLinkPageRespDTO;
import com.ayu.shortlink.project.service.RecycleBinService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.redisson.api.RBloomFilter;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

/**
 * 回收站接口实现层
 */
@Service
@RequiredArgsConstructor
public class RecycleBinServiceImpl extends ServiceImpl<ShortLinkMapper, ShortLinkDO> implements RecycleBinService {
    private final RBloomFilter<String> shortLinkCreatCachePenetrationBloomFilter;

    private final StringRedisTemplate stringRedisTemplate;

    @Override
    public void saveRecycleBin(RecycleBinSaveReqDTO requestParam) {
        //先查一层布隆过滤器 如果布隆过滤器没有 那就肯定没有
        if(!shortLinkCreatCachePenetrationBloomFilter.contains(requestParam.getFullShortUrl())){
            throw new ClientException("不存在该完整短链接");
        }

        //在查是否fullShortUrl为空值
        //为空值则肯定没有该fullShortUrl
        if(stringRedisTemplate.opsForValue().get(String.format(RedisKeyConstant.GOTO_SHORT_LINK_NULL_KEY,requestParam.getFullShortUrl())) != null){
            throw new ClientException("不存在该完整短链接");
        }

        ShortLinkDO shortLinkDO = lambdaQuery()
                .eq(ShortLinkDO::getGid, requestParam.getGid())
                .eq(ShortLinkDO::getFullShortUrl, requestParam.getFullShortUrl())
                .eq(ShortLinkDO::getDelTime,0)
                .eq(ShortLinkDO::getEnableStatus, 0)
                .eq(ShortLinkDO::getDelFlag, 0)
                .one();
        //若为空 添加该值为空值 限时30分钟
        if(shortLinkDO == null){
             stringRedisTemplate.opsForValue().set(String.format(RedisKeyConstant.GOTO_SHORT_LINK_NULL_KEY,requestParam.getFullShortUrl()),"-",30, TimeUnit.MINUTES);
             return;
        }
        //若不为空 则把它添加进回收站
        LambdaUpdateWrapper<ShortLinkDO> updateWrapper = Wrappers.lambdaUpdate(ShortLinkDO.class)
                .eq(ShortLinkDO::getGid, requestParam.getGid())
                .eq(ShortLinkDO::getFullShortUrl, requestParam.getFullShortUrl())
                .eq(ShortLinkDO::getEnableStatus, 0)
                .eq(ShortLinkDO::getDelFlag, 0);
        ShortLinkDO build = ShortLinkDO.builder()
                .delTime(System.currentTimeMillis())
                .build();
        build.setDelFlag(1);
        baseMapper.update(build,updateWrapper);
        //删掉缓存
        stringRedisTemplate.delete(String.format(RedisKeyConstant.GOTO_SHORT_LINK_KEY,requestParam.getFullShortUrl()));

    }

    @Override
    public IPage<ShortLinkPageRespDTO> getPage(ShortLinkPageReqDTO requestParam) {
        LambdaQueryWrapper<ShortLinkDO> queryWrapper = Wrappers
                .lambdaQuery(ShortLinkDO.class)
                .eq(ShortLinkDO::getGid, requestParam.getGid())
                .eq(ShortLinkDO::getDelFlag, 1);

        IPage<ShortLinkDO> resultPage = baseMapper.selectPage(requestParam, queryWrapper);
        return resultPage.convert(each -> BeanUtil.toBean(each, ShortLinkPageRespDTO.class));
    }

    @Override
    public IPage<ShortLinkPageRespDTO> getRecycleBinPage(ShortLinkRecycleBinPageReqDTO requestParam) {
        IPage<ShortLinkDO> resultPage = baseMapper.pageRecycleBinLink(requestParam);
        return resultPage.convert(each -> BeanUtil.toBean(each, ShortLinkPageRespDTO.class));
    }

    @Override
    public void recover(RecycleBinRecoverReqDTO requestParam) {
        //先查一层布隆过滤器 如果布隆过滤器没有 那就肯定没有
        if(!shortLinkCreatCachePenetrationBloomFilter.contains(requestParam.getFullShortUrl())){
            throw new ClientException("不存在该完整短链接");
        }

        LambdaUpdateWrapper<ShortLinkDO> updateWrapper = Wrappers.lambdaUpdate(ShortLinkDO.class)
                .eq(ShortLinkDO::getGid, requestParam.getGid())
                .eq(ShortLinkDO::getFullShortUrl, requestParam.getFullShortUrl())
                .eq(ShortLinkDO::getDelFlag, 1);
        ShortLinkDO build = ShortLinkDO.builder()
                .delTime(0L)
                .build();
        build.setDelFlag(0);
        baseMapper.update(build,updateWrapper);

        //删除空值
        stringRedisTemplate.delete(String.format(RedisKeyConstant.GOTO_SHORT_LINK_NULL_KEY,requestParam.getFullShortUrl()));

    }

    @Override
    public void removeRecycleBin(RecycleBinRemoveReqDTO requestParam) {
        //先查一层布隆过滤器 如果布隆过滤器没有 那就肯定没有
        if(!shortLinkCreatCachePenetrationBloomFilter.contains(requestParam.getFullShortUrl())){
            throw new ClientException("不存在该完整短链接");
        }

        LambdaUpdateWrapper<ShortLinkDO> updateWrapper = Wrappers.lambdaUpdate(ShortLinkDO.class)
                .eq(ShortLinkDO::getGid, requestParam.getGid())
                .eq(ShortLinkDO::getFullShortUrl, requestParam.getFullShortUrl())
                .eq(ShortLinkDO::getEnableStatus, 1)
                .eq(ShortLinkDO::getDelFlag, 0);
        ShortLinkDO build = ShortLinkDO.builder().build();
        build.setDelFlag(1);
        baseMapper.update(build,updateWrapper);

    }
}
